home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / PCI Driver Sample / NCR_DriverProject / Src / PrepMemoryUtilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-19  |  6.0 KB  |  203 lines  |  [TEXT/MPCC]

  1. /*                                PrepMemoryUtilities.c                                */
  2. /*
  3.  * PrepMemoryUtilities.c
  4.  * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
  5.  */
  6. /*    .___________________________________________________________________________________.
  7.       | These routines simplify the computations needed for PrepareMemoryForIO. They        |
  8.       | are not specific to the framework driver.                                            |
  9.       |                                                                                    |
  10.       |    CheckpointIOTable        Call CheckpointIO for the specified IOPreparationTable    |
  11.       |                            CompareAndSwap is used to ensure that CheckpointIO        |
  12.       |                            is called once only -- this is probably overkill        |
  13.       |    CheckForContiguousPhysicalMapping    Scan a physical mapping table to ensure        |
  14.       |                            that the entire area is physically contiguous. Since    |
  15.       |                            the driver can call MemAllocatePhysicallyContiguous,    |
  16.       |                            this isn't really needed anymore.                        |
  17.       |    NextPageIsContiguous    Return TRUE if the page following the indexed page        |
  18.       |                            is physically contiguous to the argument page. This is    |
  19.       |                            used to build the longest-possible DMA request.            |
  20.       |    GetMapEntryCount        Given a logical address and area length, return the        |
  21.       |                            number of physical map entries that will be needed.        |
  22.       |    NextPageBaseAddress        Return the base of the physical page following the        |
  23.       |                            argument physical address. This is needed to determine    |
  24.       |                            contiguous physical mappings. It could be a macro.        |
  25.       |    PageBaseAddress            Return the base of the physical page containing this    |
  26.       |                            address (which may be a logical or physical address).    |
  27.       |                            This could be a macro.                                    |
  28.       |    ClearMemory                A general subroutine to clear a block of memory. It        |
  29.       |                            tries to be efficient.                                    |
  30.     .___________________________________________________________________________________.
  31. */
  32. #include "NCRDriverPrivate.h"
  33.  
  34. /*
  35.  * This is a slightly safer version of CheckpointIO that will invalidate the
  36.  * preparationID after it completes, and will not call CheckpointIO if the
  37.  * preparationID is already invalid.
  38.  */
  39. void
  40. CheckpointIOTable(
  41.         IOPreparationTable        *ioTable
  42.  
  43.     )
  44. {
  45.         OSStatus                osStatus;
  46.         IOPreparationID            preparationID;
  47.  
  48.         Trace(CheckpointIOTable);
  49.         while ((preparationID = ioTable->preparationID) != kInvalidID) {
  50.             if (CompareAndSwap(
  51.                     (UInt32) preparationID, kInvalidID, (UInt32 *) &ioTable->preparationID)) {
  52.                 osStatus = CheckpointIO(preparationID, kNilOptions);
  53.                 CheckStatus(osStatus, "\pCheckpointIO");
  54.                 break;
  55.             } /* If CompareAndSwap succeeds */
  56.         } /* Concurrent access loop */
  57. }
  58.  
  59.  
  60. /*
  61.  * This looks at the physical mapping table to ensure that the physical area
  62.  * is contiguous. The script and per-request tables must be contiguous and the driver
  63.  * will fail to initialize if this is not the case.
  64.  */
  65. OSErr
  66. CheckForContiguousPhysicalMapping(
  67.         const IOPreparationTable *ioTable
  68.     )
  69. {
  70.         ItemCount                i;
  71.         OSErr                    status;
  72.         
  73.         //** Trace(CheckForContiguousPhysicalMapping);
  74.         status = noErr;
  75.         for (i = 0; i < ioTable->mappingEntryCount - 1; i++) {
  76.             if (NextPageIsContiguous(ioTable, i) == FALSE) {
  77.                 status = paramErr;
  78.                 break;
  79.             }
  80.         }
  81.         CheckStatus(status, "\pNon-contiguous physical mapping");
  82.         return (status);
  83. }
  84.  
  85. /*
  86.  * Return TRUE if the page following page[i] is physically contiguous with page[i].
  87.  */
  88. Boolean
  89. NextPageIsContiguous(
  90.         const IOPreparationTable *ioTable,
  91.         ItemCount                i
  92.     )
  93. {
  94.         //** Trace(NextPageIsContiguous);
  95.         return (
  96.             NextPageBaseAddress(ioTable->physicalMapping[i])
  97.                 == ioTable->physicalMapping[i + 1]
  98.             );
  99. }
  100.  
  101. /*
  102.  * Return the number of mapping tables that this area will require. There is one entry
  103.  * per page. Thus the result is the number of distinct pages in the area. areaLength
  104.  * should not be zero.
  105.  */
  106. ItemCount
  107. GetMapEntryCount(
  108.         void                    *areaBaseAddress,
  109.         ByteCount                areaLength
  110.     )
  111. {
  112.         ItemCount                result;
  113.         ByteCount                normalizedLength;
  114.         UInt32                    areaAddress;
  115.         
  116.         //** Trace(GetMapEntryCount);
  117.         areaAddress = (UInt32) areaBaseAddress;
  118.         normalizedLength = PageBaseAddress(areaAddress + areaLength - 1)
  119.                          - PageBaseAddress(areaAddress);
  120.         result = (ItemCount) (normalizedLength / GLOBAL.pageSize) + 1;
  121. #if 0 && USE_LOG_LIBRARY
  122.         WriteLogEntry(GLOBAL.logRecordPtr, 'GMap',
  123.             LogFormat5(kLogFormatAddress, kLogFormatUnsigned,
  124.                 kLogFormatUnsigned, kLogFormatUnsigned, kLogFormatString),
  125.             (UInt32) areaBaseAddress,
  126.             (UInt32) areaLength,
  127.             (UInt32) normalizedLength,
  128.             (UInt32) result,
  129.             "\pGetMapAreaCount"
  130.         );
  131. #endif
  132.         return (result);
  133. }
  134.  
  135. /*
  136.  * Return the base of the page that follows this page. This is needed to determine
  137.  * whether a logical address range is stored in a contiguous physical address
  138.  * range. This is essential for the script and script data area. Since our somewhat
  139.  * limited SCSI sample does not support scatter-gather, we check it for the SCSI
  140.  * commands, too.
  141.  */
  142. PhysicalAddress
  143. NextPageBaseAddress(
  144.         PhysicalAddress            theAddress
  145.     )
  146. {
  147.         UInt32                    result;
  148.         
  149.         //** Trace(NextPageBaseAddress);
  150.         result = PageBaseAddress((UInt32) theAddress + GLOBAL.pageSize);
  151.         return ((PhysicalAddress) result);
  152. }
  153.  
  154. /*
  155.  * Return the base of the page that contains the argument. The call to
  156.  * GetLogicalPageSize should be made at driver initialization and the mask stored in
  157.  * the driver global area.
  158.  */
  159. UInt32
  160. PageBaseAddress(
  161.         UInt32                    theAddress
  162.     )
  163. {
  164.         UInt32                    result;
  165.         
  166.         //** Trace(PageBaseAddress);
  167.         result = (theAddress & ~(GLOBAL.pageMask));
  168.         return (result);
  169. }
  170.  
  171. /*
  172.  * Clear a block of memory. This is optimized to use longword access whenever possible.
  173.  */
  174. void
  175. ClearMemory(
  176.         void                    *areaAddress,
  177.         register Size            byteCount
  178.     )
  179. {
  180.         register UInt8            *bytePtr;
  181. #define kWordSize    (sizeof (UInt32))
  182. #define kWordMask    (kWordSize - 1)
  183.  
  184.         //** Trace(ClearMemory);
  185.         bytePtr = (UInt8 *) areaAddress;
  186.         while ((((UInt32) bytePtr) & kWordMask) != 0 && byteCount > 0) {
  187.             *bytePtr++ = 0;
  188.             --byteCount;
  189.         }
  190.         while (byteCount >= kWordSize) {
  191.             *((UInt32 *) bytePtr) = 0;
  192.             bytePtr += kWordSize;
  193.             byteCount -= kWordSize;
  194.         }
  195.         while (byteCount > 0) {
  196.             *bytePtr++ = 0;
  197.             --byteCount;
  198.         }
  199. #undef kWordSize
  200. #undef kWordMax
  201. }
  202.  
  203.